﻿using System;
using System.Runtime.InteropServices;
using System.Text;
using System.ComponentModel;

namespace TibiaMC
{
    static class NativeMethods
    {
        #region Constants
        private const string NTDLL = "ntdll.dll";
        private const string KERNEL32 = "kernel32.dll";
        private const string USER32 = "user32.dll";

        public static readonly IntPtr NULL = IntPtr.Zero;
        public static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);

        public const int CNST_SYSTEM_HANDLE_INFORMATION = 0x10;
        public const uint STATUS_INFO_LENGTH_MISMATCH = 0xC0000004;
        public const uint STATUS_SUCCESS = 0x000000000;
        #endregion

        #region Enums
        [Flags]
        public enum ProcessAccessFlags : uint
        {
            All = 0x001F0FFF,
            Terminate = 0x00000001,
            CreateThread = 0x00000002,
            VMOperation = 0x00000008,
            VMRead = 0x00000010,
            VMWrite = 0x00000020,
            DupHandle = 0x00000040,
            SetInformation = 0x00000200,
            QueryInformation = 0x00000400,
            Synchronize = 0x00100000
        }

        public enum ObjectInformationClass : int
        {
            ObjectBasicInformation = 0,
            ObjectNameInformation = 1,
            ObjectTypeInformation = 2,
            ObjectAllTypesInformation = 3,
            ObjectHandleInformation = 4
        }

        public enum DuplicateOptions : uint
        {
            DUPLICATE_CLOSE_SOURCE = 0x00000001,
            DUPLICATE_SAME_ACCESS = 0x00000002
        }
        #endregion

        #region Structs
        [StructLayout(LayoutKind.Sequential)]
        public struct OBJECT_NAME_INFORMATION
        { // Information Class 1
            public UNICODE_STRING Name;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct UNICODE_STRING
        {
            public ushort Length;
            public ushort MaximumLength;
            public IntPtr Buffer;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct SYSTEM_HANDLE_TABLE_ENTRY_INFO
        {
            // Information Class 16
            public int ProcessId;
            public byte ObjectTypeNumber;
            public byte Flags;
            public ushort Handle;
            public IntPtr Object;
            public IntPtr GrantedAccess;
        }
        #endregion

        #region Functions Import
        #region ntdll
        [DllImport(NTDLL, CharSet = CharSet.Auto)]
        public static extern uint NtQuerySystemInformation(
            int query,
            IntPtr dataPtr,
            int size,
            out int returnedSize
        );

        [DllImport(NTDLL, CharSet = CharSet.Auto)]
        public static extern uint NtQueryObject(
            IntPtr ObjectHandle,
            ObjectInformationClass ObjectInformationClass,
            IntPtr ObjectInformation,
            int ObjectInformationLength,
            out int returnLength
        );
        #endregion

        #region kernel32
        [DllImport(KERNEL32, SetLastError = true, CharSet = CharSet.Auto)]
        public static extern bool DuplicateHandle(
            IntPtr hShourceProcessHandle, 
            IntPtr hSourceHandle, 
            IntPtr hTargetProcess, 
            out IntPtr TargetHandle, 
            int dwDesiredAccess,
            bool bInheritHandle, 
            DuplicateOptions dwOptions
        );

        [DllImport(KERNEL32, SetLastError = true)]
        public static extern IntPtr OpenProcess(
            ProcessAccessFlags access,
            bool inherit,
            int processId
        );

        [DllImport(KERNEL32, SetLastError = true)]
        public static extern IntPtr GetCurrentProcess();

        [DllImport(KERNEL32, SetLastError = true)]
        public static extern bool CloseHandle(IntPtr hObject);

        [DllImport(KERNEL32, SetLastError = true)]
        public static extern bool ProcessIdToSessionId(int processId, out int sessionId);
        #endregion

        #region user32
        public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);

        [DllImport(USER32, SetLastError = true)]
        public static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);

        [DllImport(USER32, SetLastError = true, CharSet = CharSet.Auto)]
        public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);

        [DllImport(USER32, SetLastError = true)]
        public static extern int GetWindowThreadProcessId(IntPtr hWnd, out int processId);
        #endregion
        #endregion
    }
}
